﻿// HSS.Interlink.FileQuery.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.html)
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2012
// ----------------------------------------------------------------------------
// File:       FileQuery.cs
// Author:     HSS\gbanta
// Created:    07/16/2011
// Modified:   07/22/2011
// ----------------------------------------------------------------------------
namespace HSS.Interlink
{
	#region Using Directives
	using System;
	using System.Text;
	using System.Globalization;

#if SILVERLIGHT
	using System.Windows.Browser;
#else
	using System.Web;
#endif

	#endregion

	#region FileQuery
	/// <summary>
	/// Contains the parts of the request query string parsed from the
	/// following format <code>jobId{0} fileName{1} command{2}</code> or
	/// if a OpenFile request then <code>open{0}</code>.
	/// </summary>
	internal static class FileQuery
	{
		#region Fields
		static string uploadTemplate = "?u={0}";
		static string downloadTemplate = "?d={0}";
		#endregion

		#region Methods

		/// <summary>
		/// Generates an UploadFile request QueryString.
		/// </summary>
		/// <param name="handler"></param>
		/// <param name="jobId"></param>
		/// <param name="fileName"></param>
		/// <param name="command"></param>
		/// <returns></returns>
		public static string CreateUploadFileQuery(string handler, Guid jobId, string fileName, FileQueryCommand command)
		{
			string query = GetEncodedQuery(handler, jobId.ToString(), fileName, command.ToString());
			return string.Format(System.Globalization.CultureInfo.InvariantCulture, uploadTemplate, query);
		}
		/// <summary>
		/// Generates a DownloadFile request QueryString.
		/// </summary>
		/// <param name="handler"></param>
		/// <param name="jobId"></param>
		/// <param name="fileName"></param>
		/// <param name="command"></param>
		/// <returns></returns>
		public static string CreateDownloadFileQuery(string handler, Guid jobId, string fileName, FileQueryCommand command)
		{
			string query = GetEncodedQuery(handler, jobId.ToString(), fileName, command.ToString());
			return string.Format(System.Globalization.CultureInfo.InvariantCulture, downloadTemplate, query);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="resourceRelativeUri"></param>
		/// <returns></returns>
		public static Uri ResolveUrl(string resourceRelativeUri)
		{
			var uri = new Uri(resourceRelativeUri, UriKind.RelativeOrAbsolute);
			if (uri.IsAbsoluteUri)
				return uri;

#if SILVERLIGHT
			else if (System.Windows.Application.Current.IsRunningOutOfBrowser)
				throw new InvalidOperationException("When running out of browser, you must specify an absolute URL.");
			else if (!System.Windows.Browser.HtmlPage.IsEnabled)
				throw new InvalidOperationException("The Html Bridge is disabled, you must specify an absolute URL.");
			else
				return new Uri(System.Windows.Browser.HtmlPage.Document.DocumentUri, resourceRelativeUri);
#else
			else
				throw new InvalidOperationException("You must specify an absolute URL.");
#endif
		}
		static string GetEncodedQuery(string handler, string jobId, string fileName, string command)
		{
			return GetEncodedQuery(DateTime.UtcNow.ToString(CultureInfo.InvariantCulture) + "," + handler + "," + jobId + "," + HttpUtility.UrlEncode(fileName) + "," + command);
		}
		static string GetEncodedQuery(string queryString)
		{
			// NOTE: this is not meant to be secure, just not plain text.
			// NOTE: uses a timestamp to prevent repeated post of a hijacked query string.
			// NOTE: uses a hash to prevent easy query string tampering, but again is not meant to 'secure' the query string.
			string query = string.Empty;
			byte[] qbytes = UTF8Encoding.UTF8.GetBytes(queryString);
			byte[] hashBytes;
			using (var sha = new System.Security.Cryptography.SHA1Managed())
				hashBytes = sha.ComputeHash(qbytes);
			byte[] data = new byte[qbytes.Length + hashBytes.Length];
			Array.Copy(qbytes, data, qbytes.Length);
			Array.Copy(hashBytes, 0, data, qbytes.Length, hashBytes.Length);
			query = Convert.ToBase64String(data);
			return HttpUtility.UrlEncode(query);
		}

		#endregion
	}
	#endregion
}